package com.hd.trans.ui.activity.customize

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.media.MediaPlayer
import android.os.Bundle
import android.os.CountDownTimer
import android.text.TextUtils
import android.view.MotionEvent
import android.view.View
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import com.hd.trans.R
import com.hd.trans.TranslationUI
import com.hd.trans.binding.visible
import com.hd.trans.callback.OnCompletionListener
import com.hd.trans.common.Constants
import com.hd.trans.common.Constants.VOICE_NORMAL
import com.hd.trans.common.Constants.VOICE_RECOGNIZING
import com.hd.trans.common.interf.VoiceComposeListener
import com.hd.trans.databinding.ActivityVoiceTranslateBinding
import com.hd.trans.db.DataBaseMgr
import com.hd.trans.db.bean.HuDunLanguage
import com.hd.trans.db.bean.TranslateRecord
import com.hd.trans.dialog.HomeVoiceRecordingPop
import com.hd.trans.extension.observe
import com.hd.trans.flagremote.FlagRemoteCore
import com.hd.trans.flagremote.SizeRemote
import com.hd.trans.framework.dialog.ConfirmDialog
import com.hd.trans.framework.dialog.EditorDlg
import com.hd.trans.framework.dialog.EditorDlg.OnInputChangedListener
import com.hd.trans.framework.dialog.LanguageDialog
import com.hd.trans.framework.dialog.LanguageDialogType
import com.hd.trans.framework.dialog.ShareDialog
import com.hd.trans.homefun.EventCode
import com.hd.trans.homefun.RecordType
import com.hd.trans.limit4Use.LimitUseListener
import com.hd.trans.network.PreferenceMgr
import com.hd.trans.network.component.HdTranslateComponent
import com.hd.trans.network.component.TranslateCallback
import com.hd.trans.share.EnShareFileType
import com.hd.trans.share.ShareTextFileManager
import com.hd.trans.ui.adapter.RecordVoiceAdapter3
import com.hd.trans.ui.base.LimitBaseActivity
import com.hd.trans.ui.base.TransInit
import com.hd.trans.ui.component.HdRecognitionComponent
import com.hd.trans.ui.component.RecognitionCallBack
import com.hd.trans.ui.component.RecordFileCallback
import com.hd.trans.ui.model.VoiceTransViewModel
import com.hd.trans.utils.ClipboardUtils
import com.hd.trans.utils.FileUtils
import com.hd.trans.utils.PermissionCallback
import com.hd.trans.utils.RecordFileCallbackImpl
import com.hd.trans.utils.ToastUtils
import com.hd.trans.utils.VoicePlayUtil
import com.hd.trans.widgets.VoicePlayView
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Objects

class VoiceTranslateActivity: LimitBaseActivity() {

    companion object {

        @JvmStatic
        fun open(context: Context, listener: LimitUseListener? = null) {
            limitListener = listener
            val intent = Intent(context, VoiceTranslateActivity::class.java)
            context.startActivity(intent)
        }
    }

    private var startTime: Long = 0L
    private var rvScrollFormUser = true
    private var rvScrollToTop = false
    private var isReverse: Boolean = false
    private var newPosition: Int = -1

    private lateinit var mDataBinding: ActivityVoiceTranslateBinding
    private lateinit var mViewModel: VoiceTransViewModel

    private var mCurrentViewVoice: VoicePlayView? = null

    /**独立处理录音文件*/
    private val mRecordFileCallbackImpl by lazy {
        RecordFileCallbackImpl()
    }

    /**语音识别组件*/
    private val mRecognitionComponent by lazy {
        HdRecognitionComponent(this,true,object : RecordFileCallback {
            override fun createRecordFile(taskId: String) {
                mRecordFileCallbackImpl.createRecordFile(taskId)
            }
            override fun writeByteToFile(bytes: ByteArray) {
                mRecordFileCallbackImpl.writeByteToFile(bytes)
            }
            override fun savePcmToWav(taskId: String) {
                mRecordFileCallbackImpl.savePcmToWav(taskId)
            }
        })
    }

    /**翻译组件*/
    private val mTranslateComponent by lazy {
        HdTranslateComponent(this)
    }

    /**tts播报组件*/
    private val voicePlayUtil by lazy {
        VoicePlayUtil.getInstance().apply {
            setOnCompletionListener(object : OnCompletionListener {
                override fun onCompletion(mp: MediaPlayer) {
                    mCurrentViewVoice?.stopPlay()
                }
            })
        }
    }

    /**分享组件*/
    private val shareMG by lazy {
        ShareTextFileManager(activity)
    }

    private val mRecordingPop by lazy {
        HomeVoiceRecordingPop(this).apply {
            setOnDismissListener {
                stopRecognize()
            }
        }
    }

    /**分享弹窗*/
    private val shareDialog by lazy {
        ShareDialog.builder()
            .setButtonColor(TransInit.getPrimaryColor())
            .setItemClickListenner { dialog, _, position ->
                when (position) {
                    0 -> shareWord(newPosition)
                    1 -> shareTxt(newPosition)
                    2 -> sharePdf(newPosition)
                }
                dialog.dismiss()
            }.build(false)
    }
    /**删除弹窗*/
    private val confirmDialog by lazy {

        ConfirmDialog.builder().setTitle("确认删除？")
            .setContent("删除后将无法恢复记录！")
            .setRightListenner(ConfirmDialog.OnComfrimDialogListenner {
                val record = mAdapter.getItem(newPosition)
                deleteInvalidFile(record){
                    mAdapter.remove(newPosition)
                    DataBaseMgr.getInstance().deleteRecord(record)
                }
            })
            .build()
    }

    private val mAdapter by lazy {
        RecordVoiceAdapter3()
    }
    private val mLayoutManager by lazy {
        LinearLayoutManager(this)
    }

    override val pageType: EventCode
        get() = EventCode.VOICE_TRANSLATE

    override fun getLayoutId(): Int {
        return R.layout.activity_voice_translate
    }

    override fun onDestroy() {
        super.onDestroy()
        voicePlayUtil.release()
    }

    override fun onPause() {
        super.onPause()
        stopPlaying()
        if(mRecordingPop.isShowing){
            stopRecognize()
        }
    }

    override fun initViewsAndEvents(savedInstanceState: Bundle?) {
        super.initViewsAndEvents(savedInstanceState)
        mDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_voice_translate)
        mViewModel = ViewModelProvider(this).get(VoiceTransViewModel::class.java)
        observe()
        initView()
        initData()
    }

    private fun observe() {
        observe(mViewModel.languageFrom) {
            mDataBinding.tvLangFrom.text = it.name
            FlagRemoteCore.loadFlagDrawable(mDataBinding.ivFlagLeft, it.translateCode, SizeRemote.W225)
        }
        observe(mViewModel.languageTo) {
            mDataBinding.tvLangTo.text = it.name
            FlagRemoteCore.loadFlagDrawable(mDataBinding.ivFlagRight, it.translateCode, SizeRemote.W225)
        }
        observe(mViewModel.operateLanguage) {
            startRecognize(it)
        }
        observe(mViewModel.voiceState) {
            updateVoiceState(it)
        }
        observe(mViewModel.isLoading) {
            updateTranslateState(it)
        }
        observe(mViewModel.operateRecord) {
        }
        val addLineNumber = 10
        observe(mViewModel.listTranslateRecord) { records ->
            records?.let {
                val currentSize = mAdapter.size()
                var subList = it
                if (currentSize == 0) {
                    if (it.size >= addLineNumber) {
                        subList = it.subList(it.size-addLineNumber, it.size)
                    }
                } else {
                    if (it.size >= currentSize + addLineNumber) {
                        subList = it.subList(it.size-currentSize-addLineNumber, it.size)
                    }
                }
                mAdapter.setList(subList)

                rvScrollToPosition(mAdapter.size() - currentSize - 1)
            }

        }
    }

    private fun initView() {
        mDataBinding.click = this

        initAdapter()
    }

    private fun initData() {
        val fromLangName = PreferenceMgr.getInstance().translatePreference.voiceFromLanguage
        val toLangName = PreferenceMgr.getInstance().translatePreference.voiceToLanguage
        mViewModel.languageFrom.value = DataBaseMgr.getInstance().getLanguageByName(fromLangName)
        mViewModel.languageTo.value = DataBaseMgr.getInstance().getLanguageByName(toLangName)

        mViewModel.refreshRecords(true)
    }

    @SuppressLint("ClickableViewAccessibility")
    private fun initAdapter() {
        mDataBinding.apply {
            recyclerView.adapter = mAdapter
            recyclerView.layoutManager = mLayoutManager

            recyclerView.addOnScrollListener(object : OnScrollListener() {
                override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                    super.onScrollStateChanged(recyclerView, newState)
                    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                        val layoutManager = recyclerView.layoutManager as LinearLayoutManager
                        val firstPosition = layoutManager.findFirstVisibleItemPosition()
                        if (rvScrollToTop && rvScrollFormUser){
                            if (firstPosition == 0){
                                //到顶了
                                mViewModel.listTranslateRecord.value?.let {
                                    if(it.size > mAdapter.size()){
                                        llProgress.visible = true
                                        mXHandler.removeCallbacks(hideProgress)
                                        mXHandler.postDelayed(hideProgress,500)
                                        mViewModel.refreshRecords(true)
                                    }else{
                                        if (mAdapter.data.isNotEmpty()){
                                            llLastBottom.visible = true
                                            mXHandler.removeCallbacks(hideTipsLastBottom)
                                            mXHandler.postDelayed(hideTipsLastBottom,500)
                                        }
                                    }
                                }

                            }
                        }

                        rvScrollFormUser = true
                    }
                }
            })

            recyclerView.setOnTouchListener(object : View.OnTouchListener{
                private var mTouchDownY = 0f
                override fun onTouch(v: View, event: MotionEvent): Boolean {
                    when(event.action){
                        MotionEvent.ACTION_DOWN -> {
                            mTouchDownY = event.y
                            rvScrollFormUser = true
                        }
                        MotionEvent.ACTION_MOVE -> {
                            rvScrollToTop = event.y - mTouchDownY > 0
                        }
                    }
                    return false
                }
            })

            mAdapter.setVoiceClickListener(object : RecordVoiceAdapter3.VoiceClickListener{
                override fun onMenuEditClick(position: Int) {
                    stopPlaying()
                    val item = mAdapter.getItem(position)
                    EditorDlg.newInstance(item.contentOrig)
                        .setOnInputChangedListener (OnInputChangedListener { value ->
                            if (value.isNotEmpty()){
                                item.contentOrig = value
                                mAdapter.notifyItemChanged(position)
                                DataBaseMgr.getInstance().updateTranslateRecord(item)

                                deleteInvalidFile(item) {
                                    //删除Tts成功后，重新翻译
                                    executeTranslate(item)
                                }
                            }
                        }).show(supportFragmentManager, "editor_dlg")
                }

                override fun onMenuCopyClick(position: Int) {
                    val item: TranslateRecord = mAdapter.getItem(position)
                    val isWrite = ClipboardUtils.writeClipText(
                        item.contentOrig + "\r\n" + item.contentTranslate)
                    if (isWrite){
                        ToastUtils.showNormal(resources.getString(R.string.copy_success_tips))
                    }
                }

                override fun onMenuShareClick(position: Int) {
                    stopPlaying()
                    newPosition = position
                    shareDialog.show(supportFragmentManager, "VoiceTranslateActivity")
                }

                override fun onMenuDeleteClick(position: Int) {
                    stopPlaying()
                    newPosition = position
                    confirmDialog.show(supportFragmentManager, "VoiceTranslateActivity")
                }

                override fun onMenuDeleteAllClick(position: Int) {
                    newPosition = position
                }

                override fun onVoicePlayClick(position: Int, voicePlayView: VoicePlayView, isTrans: Boolean) {
                    voicePlayback(voicePlayView, position, isTrans)
                }

                override fun onRetryClick(position: Int) {
                    newPosition = position
                }

                override fun onMenuCollectClick(position: Int) {
                    newPosition = position
                }
            })
        }
    }

    /**删除失效的文件*/
    private fun deleteInvalidFile(item: TranslateRecord, callback: (() -> Unit)? = null) {
        //删除录音文件
        FileUtils.deleteFile(item.voiceFile)
        item.voiceFile = ""
        voicePlayUtil.deleteTtsFile(item, true, object : Observer<Boolean?> {
            override fun onSubscribe(d: Disposable) {}
            override fun onError(e: Throwable) {}
            override fun onComplete() {
                callback?.invoke()
            }
            override fun onNext(t: Boolean) {}
        })
    }

    private fun isLimit4Use(title: String?): Boolean {
        return !intercept(false, title, null, null)
    }

    private fun isLimit4Use(code: EventCode): Boolean {
        return !intercept(code)
    }

    private val hideProgress by lazy {
        Runnable {
            mDataBinding.llProgress.visible = false
        }
    }

    private val hideTipsLastBottom by lazy {
        Runnable {
            mDataBinding.llLastBottom.visible = false
        }
    }

    private fun rvScrollToPosition(position:Int = -1){
        mDataBinding.recyclerView.post {
            rvScrollFormUser = false
            if (position == -1) {
                mLayoutManager.scrollToPositionWithOffset(mAdapter.size() - 1, 0)
            }
            else{
                mLayoutManager.scrollToPositionWithOffset(position, 0)
            }
        }
    }

    private fun shareWord(position: Int) {
        val data = mAdapter.getItem(position)?:return
        shareMG.shareTextFile(
            template(
                data.contentOrig,
                data.contentTranslate
            ), shareFileName() + ".doc", EnShareFileType.WORD_FILE
        )
    }

    private fun shareTxt(position: Int) {
        val data = mAdapter.getItem(position)?:return
        shareMG.shareTextFile(
            template(
                data.contentOrig,
                data.contentTranslate
            ), shareFileName(), EnShareFileType.TXT_FILE
        )
    }

    private fun sharePdf(position: Int) {
        val data = mAdapter.getItem(position)?:return
        shareMG.shareTextFile(
            template(
                data.contentOrig,
                data.contentTranslate
            ), shareFileName() + ".pdf", EnShareFileType.PDF_FILE
        )
    }
    /**分享内容*/
    private fun template(orgin: String?, translation: String?): String {
        return "原文:\r\n$orgin\r\n译文:\r\n$translation"
    }
    private fun shareFileName(): String {
        return SimpleDateFormat("yyyyMMdd_HHmmss").format(Date().time)
    }

    /**暂停语音播报*/
    private fun stopPlaying() {
        voicePlayUtil.stopPlay()
    }

    /**
     * 加载动画
     */
    private fun updateTranslateState(isLoading: Boolean) {
        if (isLoading){
            showLoadDialog("翻译中...")
        }else{
            hideLoadDialog()
        }
    }

    /**
     * 更新语音状态
     */
    private fun updateVoiceState(state: Int) {
        when(state){
            VOICE_NORMAL -> {
                mRecordingPop.dismiss()
            }
            VOICE_RECOGNIZING -> {
                stopPlaying()
                mRecordingPop.show()
            }
        }
    }

    private fun showSelectLanguageDialog(isFromLang: Boolean) {
        val dialog = LanguageDialog(
            Objects.requireNonNull<HuDunLanguage?>(mViewModel.languageFrom.value),
            Objects.requireNonNull<HuDunLanguage?>(mViewModel.languageTo.value),
            isFromLang, LanguageDialogType.VOICE, LanguageDialogType.TO_VOICE
        )
        dialog.show(supportFragmentManager, "LanguageDialog")
        dialog.setOnLanguageChangedListener(object : LanguageDialog.OnLanguageChangedListener{
            override fun onLanguageChanged(
                fromLanguage: HuDunLanguage,
                toLanguage: HuDunLanguage,
                selectedLanguage: HuDunLanguage
            ) {
                mViewModel.languageFrom.value = fromLanguage
                mViewModel.languageTo.value = toLanguage
                PreferenceMgr.getInstance().translatePreference
                    .saveVoiceFromLanguage(fromLanguage.name)
                PreferenceMgr.getInstance().translatePreference
                    .saveVoiceToLanguage(toLanguage.name)
            }
        })
    }

    //无语音3秒后自动关闭是识别。。
    private val mTimer by lazy {
        object : CountDownTimer(4000, 4000) {
            override fun onTick(millisUntilFinished: Long) {}

            override fun onFinish() {
                //停止语音识别
                stopRecognize()
            }
        }
    }

    /**取消定时器*/
    private fun cancelTimers() {
        mTimer.cancel()
    }

    /**停止识别*/
    private fun stopRecognize() {
        if(mViewModel.voiceState.value == VOICE_RECOGNIZING){
            cancelTimers()
            mViewModel.voiceState.value = VOICE_NORMAL
            mRecognitionComponent.stopRecognition()

            doTranslateRecord()
        }
    }

    /**执行语音识别*/
    private fun startRecognize(language: HuDunLanguage){

        if(mViewModel.voiceState.value == VOICE_RECOGNIZING){
            return
        }
        mRecordingPop.showToast()
        mRecordingPop.resetTimeChronometer()
        mViewModel.voiceState.value = VOICE_RECOGNIZING
        startTime = System.currentTimeMillis()
        mRecognitionComponent.voiceRecognition(language, object : RecognitionCallBack{

            override fun onRecognitionFailed(msg: String?, code: Int) {
                startTime = 0L
            }

            override fun onRecognitionCompleted(msg: String?, code: Int) {
                if (startTime > 0) {
                    consumeFreeTrialTime(System.currentTimeMillis() - startTime)
                    startTime = 0L
                }
            }

            override fun onRecognitionChanged(
                msg: String,
                code: Int,
                sentenceOver: Boolean,
                sentence: String?
            ) {
                if (VOICE_RECOGNIZING == mViewModel.voiceState.value) {
                    //识别到文字，说明还在说话，取消掉3秒倒计时任务
                    mTimer.cancel()
                    //重新开启3秒不说话自动关闭倒计时
                    mTimer.start()

                    mRecordingPop.hideToast()
                    mRecordingPop.setRecognitionContent(msg)
                }
            }

            override fun onVoiceChanged(waveBytes: Int, readBytes: Int) {
            }

        })
    }

    /**准备翻译*/
    private fun doTranslateRecord(){
        cancelTimers()
        val origContent = mRecordingPop.getRecognitionContent()
        if (TextUtils.isEmpty(origContent)) {
            ToastUtils.showNormal(R.string.voice_tip_null)
        } else {
            mRecordFileCallbackImpl.saveAudioFile(mRecordFileCallbackImpl.currentTaskId){ wavPath ->
                val record = TranslateRecord()
                record.isVoice = true
                record.isCollected = false
                record.isReverse = isReverse
                if(isReverse){
                    record.languageFrom = mViewModel.languageTo.value
                    record.languageTo = mViewModel.languageFrom.value
                }else{
                    record.languageFrom = mViewModel.languageFrom.value
                    record.languageTo = mViewModel.languageTo.value
                }
                record.contentOrig = origContent
                record.triggerTime = System.currentTimeMillis()
                record.voiceFile = wavPath
                record.recordType = RecordType.VOICE
                DataBaseMgr.getInstance().addTranslateRecord(record)
                mAdapter.addData(record)

                rvScrollToPosition()
                //翻译接口请求
                executeTranslate(record)
            }
        }
    }

    /**
     * 执行翻译
     */
    private fun executeTranslate(record: TranslateRecord?) {
        if (record == null || TextUtils.isEmpty(record.contentOrig)) return
        if (record.languageTo == null
            || record.languageFrom == null
        ) {
            return
        }
        record.translateState = Constants.VOICE_RECORD_TRANSLATING
        mAdapter.updateChange(record)

        DataBaseMgr.getInstance().updateTranslateRecord(record)

        mTranslateComponent.translationText(
            record.contentOrig,
            record.languageFrom.translateCode,
            record.languageTo.translateCode,
            false,
            object : TranslateCallback {
                override fun onTranslateFailed(code: Int, msg: String) {
                    if (code == Constants.ResponseCode.ERROR_IS_DANGER
                        || code == Constants.ResponseCode.ERROR_COMM
                        || code == Constants.ResponseCode.ERROR_NETWORK
                    ) {
                        ToastUtils.showError(msg)
                    } else {
                        ToastUtils.showError(R.string.fanyi_faith_tip)
                    }
                    record.translateState = Constants.VOICE_RECORD_FAILED
                    mAdapter.updateChange(record)
                    DataBaseMgr.getInstance().updateTranslateRecord(record)
                }

                override fun onTranslateCompleted(
                    data: String?,
                    fromLangCode: String,
                    toLangCode: String,
                    status: Boolean
                ) {
                    var result = data?.trim() ?: ""
                    if (result.isEmpty()){
                        ToastUtils.showNormal( R.string.fanyi_faith_tip)
                        return
                    }
                    if (result.endsWith("\n")) {
                        val endIndex = result.lastIndexOf("\n")
                        result = result.substring(0, endIndex)
                    }

                    record.contentTranslate = result
                    record.translateState = Constants.VOICE_RECORD_NORMAL
                    //自动播放
                    if (PreferenceMgr.getInstance().translatePreference.voiceAuto) {
                        mAdapter.autoPlayData = record
                    }
                    mAdapter.updateChange(record)
                    //更新到数据库
                    DataBaseMgr.getInstance().updateTranslateRecord(record)
                }
            }
        )
    }

    /**
     * 语音播报
     */
    private fun voicePlayback(mVoicePlayView: VoicePlayView, position: Int, isTransPart: Boolean) {

        if (voicePlayUtil.isPlaying) {
            voicePlayUtil.stopPlay()
        }
        if (mCurrentViewVoice != null) {
            mCurrentViewVoice!!.loadingComplete()
            if (mCurrentViewVoice!!.isPlaying()) {
                mCurrentViewVoice!!.stopPlay()
                if (mCurrentViewVoice == mVoicePlayView) return
            }
        }
        mCurrentViewVoice = mVoicePlayView

        val voiceRecord = mAdapter.getItem(position)
        if (voiceRecord.getLanguageFrom() == null
            || voiceRecord.getLanguageTo() == null
        ) {
            return
        }

        val content: String =
            if (isTransPart) voiceRecord.contentTranslate else voiceRecord.contentOrig
        if (TextUtils.isEmpty(content)) {
            return
        }
        val ttsCode: String = if (isTransPart) {
            voiceRecord.getLanguageTo().ttsCode
        } else {
            voiceRecord.getLanguageFrom().ttsCode
        }
        voicePlayUtil.executeCompositeFile(ttsCode, content, object : VoiceComposeListener {
            override fun onStarting() {
                mCurrentViewVoice!!.loading()
            }

            override fun onCompleted(file: String, isLocal: Boolean) {
                mCurrentViewVoice!!.startPlay()
                voicePlayUtil.startPlay(file)
            }

            override fun onDownloadFailed() {
                mCurrentViewVoice!!.loadingFailed()
                voicePlayUtil.stopPlay()
            }
        })
    }

    override fun onViewClick(v: View?) {
        mDataBinding.apply {
            when(v){
                back -> {
                    finish()
                }
                //设置
                btnSetting -> {
                    TranslationUI.openVoiceSettingActivity(
                        this@VoiceTranslateActivity, false)
                }
                //收藏
                btnFavorites -> {
                    TranslationUI.openFavoritesActivity(this@VoiceTranslateActivity)
                }
                //语言选择弹窗
                btnLanguageDialog -> {
                    showSelectLanguageDialog(true)
                }
                //语音识别
                btnLanguageLeft -> {
                    requestAudioPermission(PermissionCallback {
                        if(isLimit4Use(EventCode.VOICE_TRANSLATE)){
                            isReverse = false
                            mViewModel.operateLanguage.value = mViewModel.languageFrom.value
                        }
                    })
                }
                //语音识别
                btnLanguageRight -> {
                    requestAudioPermission(PermissionCallback {
                        if(isLimit4Use(EventCode.VOICE_TRANSLATE)){
                            isReverse = true
                            mViewModel.operateLanguage.value = mViewModel.languageTo.value
                        }
                    })
                }
            }
        }
    }
}